package ldh.im.fxbase.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;

public class GifCreateService {

    private static final Logger LOGGER = LoggerFactory.getLogger(GifCreateService.class);

    private ImageWriter imageWriter;
    private ImageWriteParam imageWriteParam;
    private ImageOutputStream imageOutputStream;
    private String outFile;
    private int delay;
    private boolean isInit = false;

    public GifCreateService(String outFile, int delay) {
        this.outFile = outFile;
        this.delay = delay;
        initWriter();
    }

    public void writeImage(BufferedImage bufferedImage) throws Exception {
        if (!isInit) {
            isInit = true;

            initOutputStream();
            init(bufferedImage);
        }

        imageWriter.writeToSequence(new javax.imageio.IIOImage(bufferedImage, null, null), null);
    }

    public void close() throws IOException {
        imageWriter.endWriteSequence();
        if (imageOutputStream != null) {
            imageOutputStream.close();
        }
        LOGGER.info("gif close");
    }

    private void initWriter() {
        // 设置GIF编码参数
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("gif");
        if (!writers.hasNext()) {
            throw new IllegalStateException("No writers found");
        }
        imageWriter = writers.next();
        imageWriteParam = imageWriter.getDefaultWriteParam();
        imageWriteParam.setDestinationType(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB));
        imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        //设置高质量压缩
        if (imageWriteParam.canWriteCompressed()) {
            String[] cs = imageWriteParam.getCompressionTypes();
            imageWriteParam.setCompressionType(cs[0]);
            imageWriteParam.setCompressionQuality(0.3f);
        }
    }

    private void initOutputStream() throws IOException {
        imageOutputStream = ImageIO.createImageOutputStream(new File(outFile));
        imageWriter.setOutput(imageOutputStream);
        imageWriter.prepareWriteSequence(null);
    }

    private void init(BufferedImage bufferedImage) throws IIOInvalidTreeException {
        // 设置延迟时间（以毫秒为单位）
        IIOMetadata metadata = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(bufferedImage.getColorModel(), bufferedImage.getSampleModel()), imageWriteParam);
        String metaFormatName = metadata.getNativeMetadataFormatName();
        IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(metaFormatName);

        // 设置全局延迟时间
        IIOMetadataNode graphicsControlExtension = new IIOMetadataNode("GraphicControlExtension");
        graphicsControlExtension.setAttribute("disposalMethod", "none"); // 恢复前一帧
        graphicsControlExtension.setAttribute("delayTime", Integer.toString(delay)); // 延迟时间（以1/100秒为单位）
        graphicsControlExtension.setAttribute("transparentColorIndex", "0"); // 透明色索引，如果有的话
        graphicsControlExtension.setAttribute("userInputFlag", "false");
        graphicsControlExtension.setAttribute("transparentColorFlag", "false");

        root.appendChild(graphicsControlExtension);
        metadata.setFromTree(metaFormatName, root);
    }

}
